#include "dxgameinput.h"
#include "logger.h"

using namespace std;

DXGameInput::DXGameInput() 
{ }

DXGameInput::DXGameInput(HWND hWindow)
{	
    hInstance = (HINSTANCE)GetModuleHandle(NULL);
    hWnd = hWindow;
    pDInput = NULL;
    pKeyboardDevice = NULL;
    pMouseDevice = NULL;
    for (int i = 0; i < 256; ++i)
        keyPress[i] = false;
}

bool DXGameInput::Init()
{	
    //Init directX input
    if (FAILED(DirectInput8Create(hInstance,
                                    DIRECTINPUT_VERSION,
                                    IID_IDirectInput8,
                                    (void**)&pDInput,
                                    NULL)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't create DirectInput!");
        return false;
    }
    //Init keyboard device
    if (FAILED(pDInput->CreateDevice(GUID_SysKeyboard, &pKeyboardDevice, NULL)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't create Keyboard Device!");
        return false;
    }
    if (FAILED(pKeyboardDevice->SetDataFormat(&c_dfDIKeyboard)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't set data format Keyboard!");
        return false;
    }
    if (FAILED(pKeyboardDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't set cooperative level Keyboard!");
        return false;
    }
    //Set buffered input to read buffered data
    DIPROPDWORD dipdw;
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj        = 0;
    dipdw.diph.dwHow        = DIPH_DEVICE;
    dipdw.dwData            = KEYBOARD_BUFFER_SIZE;
    if (FAILED(pKeyboardDevice->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
        return false;
        
    //Init mouse device
    if (FAILED(pDInput->CreateDevice(GUID_SysMouse, &pMouseDevice, NULL)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't create Mouse Device!");
        return false;
    }
    if (FAILED(pMouseDevice->SetDataFormat(&c_dfDIMouse)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't set data format Mouse!");
        return false;
    }
    if (FAILED(pMouseDevice->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE)))
    {	
        (Logger::GetLogger("DXGameInput")).Error("Can't set cooperative level Mouse!");
        return false;
    }
    return true;
}

void DXGameInput::GetState()
{	
    //poll state of the keyboard
    pKeyboardDevice->Poll();
    if (FAILED(pKeyboardDevice->GetDeviceState(sizeof(keyState),(LPVOID)&keyState)))
    {
        //keyboard device lost, try to re-acquire
        pKeyboardDevice->Acquire();
        pKeyboardDevice->GetDeviceState(sizeof(keyState),(LPVOID)&keyState);
    }
    DWORD dwElements = KEYBOARD_BUFFER_SIZE;
    pKeyboardDevice->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keyEvent, &dwElements, 0);

    //poll state of the mouse
    pMouseDevice->Poll();
    if (FAILED(pMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE),&mouseState)))
    {
        //mouse device lose, try to re-acquire
        pMouseDevice->Acquire();
        pMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE),&mouseState);
    }

    //get mouse position on screen
    GetCursorPos(&position);
    ScreenToClient(hWnd, &position);
    return;

}

bool DXGameInput::IsKeyDown(unsigned char key)
{	
    if (keyState[key] & MASK)
        return true;
    return false;
}

bool DXGameInput::IsKeyUp(unsigned char key)
{	
    return !IsKeyDown(key);
}

bool DXGameInput::IsKeyPress(unsigned char key)
{	
    if (keyPress[key] == true)
    {	
        if (IsKeyUp(key))
        {	
            keyPress[key] = false;
            return true;
        }
    }
    else if (IsKeyDown(key))
        keyPress[key] = true;
    return false;
}

bool DXGameInput::IsKeyRelease(unsigned char key)
{	
    return !IsKeyPress(key);
}

bool DXGameInput::IsMouseDown(unsigned char button)
{	
    if (mouseState.rgbButtons[button] & MASK)
        return true;
    return false;
}

bool DXGameInput::IsMouseUp(unsigned char button)
{	
    return !IsMouseDown(button);
}

bool DXGameInput::IsMouseMove()
{	
    if ((GetMouseMove_X() != 0) || (GetMouseMove_Y() != 0))
        return true;
    else
        return false;
}

float DXGameInput::GetMouseMove_X()
{	
    return (float)mouseState.lX;
}

float DXGameInput::GetMouseMove_Y()
{	
    return (float)mouseState.lY;
}

float DXGameInput::GetMouseMove_Z()
{	
    return (float)mouseState.lZ;
}

float DXGameInput::GetPosX()
{	return (float)position.x;
}

float DXGameInput::GetPosY()
{	
    return (float)position.y;
}

DXGameInput::~DXGameInput()
{	
    if (pKeyboardDevice != NULL)
    {	
        pKeyboardDevice->Unacquire();
        pKeyboardDevice->Release();
    }

    if (pMouseDevice != NULL)
    {	
        pMouseDevice->Unacquire();
        pMouseDevice->Release();
    }

    if (pDInput != NULL)
        pDInput->Release();
}